﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace KINLO.DRV.Drv
{
    public class IVModbusDrv
    {
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(IVModbusDrv));
        string IP;
        int Port;
        int NNetId;


        #region //标准库
        [DllImport("StandardModbusApi.dll", EntryPoint = "Init_ETH_String", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool Init_ETH_String(string sIpAddr, int nNetId = 0, int IpPort = 502);

        [DllImport("StandardModbusApi.dll", EntryPoint = "Exit_ETH", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool Exit_ETH(int nNetId = 0);

        //[DllImport("StandardModbusApi.dll", EntryPoint = "H3u_Write_Soft_Elem", CallingConvention = CallingConvention.Cdecl)]
        //public static extern int H3u_Write_Soft_Elem(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0);

        //[DllImport("StandardModbusApi.dll", EntryPoint = "H3u_Read_Soft_Elem", CallingConvention = CallingConvention.Cdecl)]
        //public static extern int H3u_Read_Soft_Elem(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0);

        //[DllImport("StandardModbusApi.dll", EntryPoint = "H3u_Read_Soft_Elem_Float", CallingConvention = CallingConvention.Cdecl)]
        //public static extern int H3u_Read_Soft_Elem_Float(SoftElemType eType, int nStartAddr, int nCount, float[] pValue, int nNetId = 0);
        public IVModbusDrv(string ip,int port,int nNetId)
        {
            this.IP = ip;
            this.Port = port;
            this.NNetId = nNetId;
        }


        /// <summary>
        /// 打开连接
        /// </summary>
        /// <returns></returns>
        public bool Open()
        {
            var a= Init_ETH_String(IP, NNetId, Port);
            return a;
        }
        /// <summary>
        /// 关闭连接
        /// </summary>
        /// <returns></returns>
        public bool Disconnect()
        {
            return Exit_ETH( NNetId);
        }

        /// <summary>
        /// 初始化连接
        /// </summary>
        /// <param name="sIpAddr">IP地址</param>
        /// <param name="nNetId">网络链接编号</param>
        /// <param name="IpPort">端口号</param>
        /// <returns></returns>
         public bool InitETHString(string sIpAddr, int nNetId = 0, int IpPort = 502)
        {
            var result = Init_ETH_String(sIpAddr, nNetId, IpPort);
            Console.WriteLine(result);
            Connected = true;
            return result;
        }
        /// <summary>
        /// 关闭连接
        /// </summary>
        /// <param name="nNetId">网络链接编号</param>
        /// <returns></returns>
         public bool  ExitETH(int nNetId = 0)
        {
            var result=  Exit_ETH( nNetId );
            Connected = false;
            return result;
        }
        bool connected;
        public bool Connected
        {
            get { return connected; }
            set { connected = value; }
        }

        /******************************************************************************
         1.功能描述 : 写Am600软元件
         2.返 回 值 :1 成功  0 失败
         3.参    数 : nNetId:网络链接编号
			          eType：软元件类型    ELEM_QX = 0//QX元件  ELEM_MW = 1 //MW元件
			          nStartAddr:软元件起始地址（QX元件由于带小数点，地址需要乘以10去掉小数点，如QX10.1，请输入101，MW元件直接就是它的元件地址不用处理）
			          nCount：软元件个数
			          pValue：数据缓存区
        4.注意事项 :  1.x和y元件地址需为8进制; 
			          2. 当元件位C元件双字寄存器时，每个寄存器需占4个字节的数据
			          3.如果是写位元件，每个位元件的值存储在一个字节中
        ******************************************************************************/
        [DllImport("StandardModbusApi.dll", EntryPoint = "Am600_Write_Soft_Elem", CallingConvention = CallingConvention.Cdecl)]
        public static extern int Am600_Write_Soft_Elem(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0);
        [DllImport("StandardModbusApi.dll", EntryPoint = "Am600_Write_Soft_Elem_Int16", CallingConvention = CallingConvention.Cdecl)]
        public static extern int Am600_Write_Soft_Elem_Int16(SoftElemType eType, int nStartAddr, int nCount, short[] pValue, int nNetId = 0);
        [DllImport("StandardModbusApi.dll", EntryPoint = "Am600_Write_Soft_Elem_Int32", CallingConvention = CallingConvention.Cdecl)]
        public static extern int Am600_Write_Soft_Elem_Int32(SoftElemType eType, int nStartAddr, int nCount, long[] pValue, int nNetId = 0);
        [DllImport("StandardModbusApi.dll", EntryPoint = "Am600_Write_Soft_Elem_UInt16", CallingConvention = CallingConvention.Cdecl)]
        public static extern int Am600_Write_Soft_Elem_UInt16(SoftElemType eType, int nStartAddr, int nCount, ushort[] pValue, int nNetId = 0);
        [DllImport("StandardModbusApi.dll", EntryPoint = "Am600_Write_Soft_Elem_UInt32", CallingConvention = CallingConvention.Cdecl)]
        public static extern int Am600_Write_Soft_Elem_UInt32(SoftElemType eType, int nStartAddr, int nCount, ulong[] pValue, int nNetId = 0);
        [DllImport("StandardModbusApi.dll", EntryPoint = "Am600_Write_Soft_Elem_Float", CallingConvention = CallingConvention.Cdecl)]
        public static extern int Am600_Write_Soft_Elem_Float(SoftElemType eType, int nStartAddr, int nCount, float[] pValue, int nNetId = 0);

        /// <summary>
        /// 写通信点  
        /// </summary>
        /// <param name="eType">类型</param>
        /// <param name="nStartAddr">起始地址</param>
        /// <param name="nCount">个数</param>
        /// <param name="pValue">值数组</param>
        /// <param name="nNetId">网络链接编号</param>
        /// <returns>1 成功  0 失败</returns>
        public int WriteSoftElem(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0)
        {
           return Am600_Write_Soft_Elem(eType, nStartAddr, nCount, pValue, nNetId);
        }

        /// <summary>
        /// 写通信点 16位
        /// </summary>
        /// <param name="eType">类型</param>
        /// <param name="nStartAddr">起始地址</param>
        /// <param name="nCount">个数</param>
        /// <param name="pValue">值数组</param>
        /// <param name="nNetId">网络链接编号</param>
        /// <returns>1 成功  0 失败</returns>
        public int WriteSoftElem16(SoftElemType eType, int nStartAddr, int nCount, short[] pValue, int nNetId = 0)
        {
            return Am600_Write_Soft_Elem_Int16(eType, nStartAddr, nCount, pValue, nNetId);
        }

        /// <summary>
        /// 写通信点 32位
        /// </summary>
        /// <param name="eType">类型</param>
        /// <param name="nStartAddr">起始地址</param>
        /// <param name="nCount">个数</param>
        /// <param name="pValue">值数组</param>
        /// <param name="nNetId">网络链接编号</param>
        /// <returns>1 成功  0 失败</returns>
        public int WriteSoftElem32(SoftElemType eType, int nStartAddr, int nCount, long[] pValue, int nNetId = 0)
        {
            return Am600_Write_Soft_Elem_Int32(eType, nStartAddr, nCount, pValue, nNetId);
        }

        /// <summary>
        /// 写通信点 无符号16位
        /// </summary>
        /// <param name="eType">类型</param>
        /// <param name="nStartAddr">起始地址</param>
        /// <param name="nCount">个数</param>
        /// <param name="pValue">值数组</param>
        /// <param name="nNetId">网络链接编号</param>
        /// <returns>1 成功  0 失败</returns>
        public int WriteSoftElemU16(SoftElemType eType, int nStartAddr, int nCount, ushort[] pValue, int nNetId = 0)
        {
            return Am600_Write_Soft_Elem_UInt16(eType, nStartAddr, nCount, pValue, nNetId);
        }

        /// <summary>
        /// 写通信点 无符号32位
        /// </summary>
        /// <param name="eType">类型</param>
        /// <param name="nStartAddr">起始地址</param>
        /// <param name="nCount">个数</param>
        /// <param name="pValue">值数组</param>
        /// <param name="nNetId">网络链接编号</param>
        /// <returns>1 成功  0 失败</returns>
        public int WriteSoftElemU32(SoftElemType eType, int nStartAddr, int nCount, ulong[] pValue, int nNetId = 0)
        {
            return Am600_Write_Soft_Elem_UInt32(eType, nStartAddr, nCount, pValue, nNetId);
        }

        /// <summary>
        /// 写通信点 浮点
        /// </summary>
        /// <param name="eType">类型</param>
        /// <param name="nStartAddr">起始地址</param>
        /// <param name="nCount">个数</param>
        /// <param name="pValue">值数组</param>
        /// <param name="nNetId">网络链接编号</param>
        /// <returns>1 成功  0 失败</returns>
        public int WriteSoftElemFloat(SoftElemType eType, int nStartAddr, int nCount, float[] pValue, int nNetId = 0)
        {
            return Am600_Write_Soft_Elem_Float(eType, nStartAddr, nCount, pValue, nNetId);
        } 

        /******************************************************************************
         1.功能描述 : 读Am600软元件
         2.返 回 值 :1 成功  0 失败
         3.参    数 : nNetId:网络链接编号
			          eType：软元件类型   ELEM_QX = 0//QX元件  ELEM_MW = 1 //MW元件
			          nStartAddr:软元件起始地址（QX元件由于带小数点，地址需要乘以10去掉小数点，如QX10.1，请输入101，其它元件不用处理）
			          nCount：软元件个数
			          pValue：返回数据缓存区
         4.注意事项 : 如果是读位元件，每个位元件的值存储在一个字节中，pValue数据缓存区字节数必须是8的整数倍
        ******************************************************************************/
 
        [DllImport("StandardModbusApi.dll", EntryPoint = "Am600_Read_Soft_Elem", CallingConvention = CallingConvention.Cdecl)]
        public static extern int Am600_Read_Soft_Elem(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0);
 
        [DllImport("StandardModbusApi.dll", EntryPoint = "Am600_Read_Soft_Elem_Int16", CallingConvention = CallingConvention.Cdecl)]
        public static extern int Am600_Read_Soft_Elem_Int16(SoftElemType eType, int nStartAddr, int nCount, short[] pValue, int nNetId = 0);  
        [DllImport("StandardModbusApi.dll", EntryPoint = "Am600_Read_Soft_Elem_Int32", CallingConvention = CallingConvention.Cdecl)]
        public static extern int Am600_Read_Soft_Elem_Int32(SoftElemType eType, int nStartAddr, int nCount, long[] pValue, int nNetId = 0); 
        [DllImport("StandardModbusApi.dll", EntryPoint = "Am600_Read_Soft_Elem_UInt16", CallingConvention = CallingConvention.Cdecl)]
        public static extern int Am600_Read_Soft_Elem_UInt16(SoftElemType eType, int nStartAddr, int nCount, ushort[] pValue, int nNetId = 0); 
        [DllImport("StandardModbusApi.dll", EntryPoint = "Am600_Read_Soft_Elem_UInt32", CallingConvention = CallingConvention.Cdecl)]
        public static extern int Am600_Read_Soft_Elem_UInt32(SoftElemType eType, int nStartAddr, int nCount, ulong[] pValue, int nNetId = 0); 
        [DllImport("StandardModbusApi.dll", EntryPoint = "Am600_Read_Soft_Elem_Float", CallingConvention = CallingConvention.Cdecl)]
        public static extern int Am600_Read_Soft_Elem_Float(SoftElemType eType, int nStartAddr, int nCount, float[] pValue, int nNetId = 0);

        /// <summary>
        /// 读通信点 
        /// </summary>
        /// <param name="eType">类型</param>
        /// <param name="nStartAddr">起始地址</param>
        /// <param name="nCount">软元件个数</param>
        /// <param name="pValue">返回数据缓存区</param>
        /// <param name="nNetId">网络链接编号</param>
        /// <returns>返回值  1 成功  0 失败</returns>
        public int ReadSoftElem(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0)
        {
            return Am600_Read_Soft_Elem( eType,  nStartAddr,  nCount, pValue,  nNetId );
        }

        /// <summary>
        /// 读通信点  16位
        /// </summary>
        /// <param name="eType">类型</param>
        /// <param name="nStartAddr">起始地址</param>
        /// <param name="nCount">软元件个数</param>
        /// <param name="pValue">返回数据缓存区</param>
        /// <param name="nNetId">网络链接编号</param>
        /// <returns>返回值  1 成功  0 失败</returns>
        public int ReadSoftElem16(SoftElemType eType, int nStartAddr, int nCount, short[] pValue, int nNetId = 0)
        {
            return Am600_Read_Soft_Elem_Int16(eType, nStartAddr, nCount, pValue, nNetId);
        }

        /// <summary>
        /// 读通信点 32位
        /// </summary>
        /// <param name="eType">类型</param>
        /// <param name="nStartAddr">起始地址</param>
        /// <param name="nCount">软元件个数</param>
        /// <param name="pValue">返回数据缓存区</param>
        /// <param name="nNetId">网络链接编号</param>
        /// <returns>返回值  1 成功  0 失败</returns>
        public int ReadSoftElem32(SoftElemType eType, int nStartAddr, int nCount, long[] pValue, int nNetId = 0)
        {
            return Am600_Read_Soft_Elem_Int32(eType, nStartAddr, nCount, pValue, nNetId);
        }

        /// <summary>
        /// 读通信点 U16位
        /// </summary>
        /// <param name="eType">类型</param>
        /// <param name="nStartAddr">起始地址</param>
        /// <param name="nCount">软元件个数</param>
        /// <param name="pValue">返回数据缓存区</param>
        /// <param name="nNetId">网络链接编号</param>
        /// <returns>返回值  1 成功  0 失败</returns>
        public int ReadSoftElemU16(SoftElemType eType, int nStartAddr, int nCount, ushort[] pValue, int nNetId = 0)
        {
            return Am600_Read_Soft_Elem_UInt16(eType, nStartAddr, nCount, pValue, nNetId);
        }

        /// <summary>
        /// 读通信点 U32位
        /// </summary>
        /// <param name="eType">类型</param>
        /// <param name="nStartAddr">起始地址</param>
        /// <param name="nCount">软元件个数</param>
        /// <param name="pValue">返回数据缓存区</param>
        /// <param name="nNetId">网络链接编号</param>
        /// <returns>返回值  1 成功  0 失败</returns>
        public int ReadSoftElemU32(SoftElemType eType, int nStartAddr, int nCount, ulong[] pValue, int nNetId = 0)
        {
            return Am600_Read_Soft_Elem_UInt32(eType, nStartAddr, nCount, pValue, nNetId);
        }

        /// <summary>
        /// 读通信点  浮点
        /// </summary>
        /// <param name="eType">类型</param>
        /// <param name="nStartAddr">起始地址</param>
        /// <param name="nCount">软元件个数</param>
        /// <param name="pValue">返回数据缓存区</param>
        /// <param name="nNetId">网络链接编号</param>
        /// <returns>返回值  1 成功  0 失败</returns>
        public int ReadSoftElemFloat(SoftElemType eType, int nStartAddr, int nCount, float[] pValue, int nNetId = 0)
        {
            return Am600_Read_Soft_Elem_Float(eType, nStartAddr, nCount, pValue, nNetId);
        }

        #endregion

    }
}
